import asyncio

print("..............async...........................")


# 1. async def 定义协程函数
async def func1():
    print("... 协程函数")


#  获取协程对象：并不会执行方法，而是得到了一个协程对象
f1 = func1()

# # 把任务添加到事件循环组中并执行，python3.6 写法
# loop = asyncio.get_event_loop()  # 获取事件循环组
# loop.run_until_complete(f1)  # 执行协程

# 把任务添加到事件循环组中并执行，python3.7 写法
asyncio.run(f1)
print("..............await 1...........................")


# 2. await
# await + 可等待的对象（协程对象、Future对象、Task对象 --> IO等待）
async def func2():
    print("... 协程函数")
    resp = await asyncio.sleep(5)
    print("等待结束，返回结果：", resp)


asyncio.run(func2())
print("................await 2.........................")


async def nest_func():
    print("... start")
    await asyncio.sleep(5)
    print("... end")
    return "success"


async def func3():
    print("... 执行协程函数内部代码")
    resp = await nest_func()
    print("... IO 请求结束，结果为：", resp)
    return "success"


async def func4():
    print("。。。。 执行其他方法")
    await asyncio.sleep(10)


# 包装一下 func3，func4
async def func5():
    await asyncio.gather(func3(), func4())


asyncio.run(func5())
print("................task 1.........................")


# task
# 添加多个任务
# Task用于在事件循环中并发调度协程，通过封装协程对象实现并发执行。
# 创建Task的推荐方法
#   1.使用 asyncio.create_task(coroutine)（Python 3.7+）
#       示例：task = asyncio.create_task(my_coroutine())
#   2.事件循环的 loop.create_task() 方法（Python 3.5+）
#   3.通用函数 asyncio.ensure_future()（可接受协程/Future/Task）
async def func6():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "success"


async def func7():
    print('main 开始')
    # 创建task对象，将当前执行fun函数任务添加到事件循环中
    task1 = asyncio.create_task(func6())

    task2 = asyncio.create_task(func6())

    print('main 结束')
    # 当执行协程遇到IO操作时，自动切换到其他任务
    # 此时await 是等待响应的协程结束，返回结果
    result1 = await task1
    result2 = await task2
    print(result1, result2)


asyncio.run(func7())
print("................task 2.........................")


async def func8(time: int):
    print(1)
    await asyncio.sleep(time)
    print(2)
    return "success"


async def func9():
    print('main 开始')
    # 创建task对象，将当前执行fun函数任务添加到事件循环中
    task_list = [
        asyncio.create_task(func8(2), name="task1"),
        asyncio.create_task(func8(5), name="task2")
    ]

    print('main 结束')

    # timeout : 任务执行的超时事件 默认None（即不设超时时间）
    # done : 所有在超时时间内完成的task的返回值
    # pending ：在超时时间内没有完成的task
    done, pending = await asyncio.wait(task_list, timeout=4)
    print('done:', done, '\n', 'pending:', pending)


asyncio.run(func9())
print("................task 3.........................")


async def func10(time: int):
    print(1)
    await asyncio.sleep(time)
    print(2)
    return "success"

task_list = [func10(2), func10(5)]
done, pending = asyncio.run(asyncio.wait(task_list))
print('done:', done, '\n', 'pending:', pending)


